package top.v5it.logback.push.channel.weixin;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.function.Consumer;

/**
 * 企业徾信webhook请求工具
 *
 * @author zhanpu
 * @date 2021/7/25
 */
@Slf4j
public class WeiXinUtil {

    /**
     * 默认请求服务超时时间
     */
    private static final int DEFAULT_TIMEOUT = 15 * 1000;

    private WeiXinUtil() {
        throw new UnsupportedOperationException();
    }

    /**
     * 向企业徾信群发送消息
     *
     * @param url     群消息地址
     * @param request 请求参数
     * @param timeout 超时时间
     * @return {@link WeiXinRobotSendResponse}
     */
    public static WeiXinRobotSendResponse send(String url, WeiXinRobotSendRequest request, int timeout) {
        Assert.notBlank(url, "发送企业徾信息消息，服务地址不能为空");
        Assert.notNull(request, "发送企业徾信息消息，请求参数不能为空");
        final String jsonStr = JSONUtil.toJsonStr(request);
        return send(url, jsonStr, timeout);
    }

    /**
     * 向企业徾信群发送消息
     *
     * @param url     群消息地址
     * @param jsonStr 请求参数
     * @param timeout 超时时间
     * @return {@link WeiXinRobotSendResponse}
     */
    public static WeiXinRobotSendResponse send(String url, String jsonStr, int timeout) {
        Assert.notBlank(url, "发送企业徾信息消息，服务地址不能为空");
        Assert.notBlank(jsonStr, "发送企业徾信息消息，请求参数不能为空");
        log.trace(">>>>>\n请求地址：{}\n请求参数：{}\n", url, jsonStr);
        String result = HttpUtil.post(url, jsonStr, (timeout == 0 ? DEFAULT_TIMEOUT : timeout));
        log.trace(">>>>>返回结果：{}", result);
        return converter(result);
    }

    public static void asyncSend(String url, WeiXinRobotSendRequest request, int timeout, Consumer<HttpResponse> consumer) {
        Assert.notBlank(url, "发送企业徾信息消息，服务地址不能为空");
        Assert.notNull(request, "发送企业徾信息消息，请求参数不能为空");
        final String jsonStr = JSONUtil.toJsonStr(request);
        asyncSend(url, jsonStr, timeout, consumer);
    }

    public static void asyncSend(String url, String jsonStr, int timeout, Consumer<HttpResponse> consumer) {
        Assert.notBlank(url, "发送企业徾信息消息，服务地址不能为空");
        Assert.notBlank(jsonStr, "发送企业徾信息消息，请求参数不能为空");
        HttpRequest.post(url)
                .timeout((timeout == 0 ? DEFAULT_TIMEOUT : timeout))
                .body(jsonStr)
                .then(consumer);
    }

    /**
     * 向企业徾信上传文件
     *
     * @param url     上传文件地址
     * @param file    文件
     * @param timeout 超时时间
     * @return {@link WeiXinRobotSendResponse}
     */
    public static WeiXinRobotSendResponse upload(String url, File file, int timeout) {
        Assert.notBlank(url, "上传文件至企业徾信，服务地址不能为空");
        Assert.notNull(file, "上传文件不能为空");
        url = url.replace("send", "upload_media");
        url += "&type=file";
        log.trace(">>>>>\n请求地址：{}\n请求参数：{}\n", url, file.getPath());
        String result = HttpUtil.post(url, MapUtil.of("media", file), (timeout == 0 ? DEFAULT_TIMEOUT : timeout));
        log.trace(">>>>>返回结果：{}", result);
        return converter(result);
    }

    /**
     * 转换
     *
     * @param result 字符
     * @return @return {@link WeiXinRobotSendResponse}
     */
    private static WeiXinRobotSendResponse converter(String result) {
        WeiXinRobotSendResponse response = JSONUtil.toBean(result, WeiXinRobotSendResponse.class);
        if (response.getErrcode().compareTo(0) == 0) return response;
        log.error(result);
        throw new IllegalArgumentException(response.getErrmsg());
    }
}
